import type { AnimationType } from './types'

function animate(
  target: string | HTMLElement,
  type: AnimationType,
  duration: number = 300,
  timingFn: string = 'ease'
): Promise<HTMLElement | undefined> {
  return new Promise((resolve) => {
    const e = typeof target === 'string' ? document.getElementById(target) : target
    if (!e) {
      resolve(undefined)
      return
    }
    e.style.animation = `${type} ${duration}ms ${timingFn}`
    setTimeout(() => {
      e.style.animation = ''
      resolve(e)
    }, duration - 23)
  })
}

export async function fadeIn(target: string | HTMLElement, duration: number = 300) {
  await animate(target, 'fadeIn', duration, 'ease')
}

export async function fadeOut(target: string | HTMLElement, duration: number = 300) {
  const e = await animate(target, 'fadeOut', duration, 'ease')
  if (e) {
    e.style.visibility = 'hidden'
  }
}

export async function slideInLeft(target: string | HTMLElement, duration: number = 300) {
  await animate(target, 'slideInLeft', duration, 'ease')
}

export async function slideOutLeft(target: string | HTMLElement, duration: number = 300) {
  const e = await animate(target, 'slideOutLeft', duration, 'ease')
  if (e) {
    e.style.visibility = 'hidden'
  }
}

export async function slideInRight(target: string | HTMLElement, duration: number = 300) {
  await animate(target, 'slideInRight', duration, 'ease')
}

export async function slideOutRight(target: string | HTMLElement, duration: number = 300) {
  const e = await animate(target, 'slideOutRight', duration, 'ease')
  if (e) {
    e.style.visibility = 'hidden'
  }
}

export async function slideInTop(target: string | HTMLElement, duration: number = 300) {
  await animate(target, 'slideInTop', duration, 'ease')
}

export async function slideOutTop(target: string | HTMLElement, duration: number = 300) {
  const e = await animate(target, 'slideOutTop', duration, 'ease')
  if (e) {
    e.style.visibility = 'hidden'
  }
}

export async function slideInBottom(target: string | HTMLElement, duration: number = 300) {
  await animate(target, 'slideInBottom', duration, 'ease')
}

export async function slideOutBottom(target: string | HTMLElement, duration: number = 300) {
  const e = await animate(target, 'slideOutBottom', duration, 'ease')
  if (e) {
    e.style.visibility = 'hidden'
  }
}
